/*  tBookShelf: Hyphenation class
    (C) 2007  TvN (Volodymyr Tarasenko), e-mail: tvntsr@yahoo.com

    Based on LibHnj - a library for high quality hyphenation and justification
    Copyright (C) 1998 Raph Levien
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef HYPHENATION_DICTIONARY_HPP
#define HYPHENATION_DICTIONARY_HPP

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <stdexcept>

#include <ext/hash_map>

//#include <tr1/hashtable>
//#include <map>

#include "Utils/SharedPtr.hpp"

/**
 * HyphenDict uses standard TeX hyphenation algorithm and dictionaries
 * Dictionaries could be taken from OpenOffice suit: 
 * http://wiki.services.openoffice.org/wiki/Dictionaries
 */

class HyphenDict
{
private:
    typedef __gnu_cxx::hash_map<std::string, int> HashTab;
//    typedef std::map<std::string, int> HashTab;
//    typedef std::tr1::hashtable<std::string, int> HashTab;
    struct HyphenTrans 
    {
        char ch;
        int  new_state;

        HyphenTrans(const char& c, const int& n)
            : ch(c), new_state(n)
        {}
    };

    struct HyphenState 
    {
        typedef std::vector<HyphenTrans> trans_type_el;
        typedef SharedPtr<trans_type_el> trans_type;

        std::string match;
        int         fallback_state;
        trans_type  trans;

        HyphenState()
            : match(), 
              fallback_state(-1),
              trans(new trans_type_el)
        {}

        HyphenState(const HyphenState& i)
            : match(i.match), 
              fallback_state(i.fallback_state),
              trans(i.trans)
        {}

        HyphenState& operator=(const HyphenState& i)
        {
            match = i.match;
            trans = i.trans;
            fallback_state = i.fallback_state;

            return *this;
        }
    };

public:
    HyphenDict(const std::string& load_from)    
        : cset()
    {
        std::ifstream f(load_from.c_str());
        if (!f)
        {
            throw std::runtime_error("Cannot open hyphenation dictionary, bad file");
        }
        read_dict(f);
    }
    
    HyphenDict(std::istream& from)
        : cset()
    {
        read_dict(from);
    }

    ~HyphenDict()
    {}

    void hyphenate(const std::string& word,
                   std::string& hyphens);

    const std::string& dictCharset() const
    {
        return cset;
    }

private:
    int  get_state(HashTab& hashtab, const std::string& str);
    void add_trans(const int& state1, const int& state2, const char& ch);

    void read_dict(std::istream&);
private:
    std::vector<HyphenState> dict;
    std::string              cset;
};



#endif //HYPHENATION_DICTIONARY_HPP
